<template>
  <div class="home">
    <el-container style="height: 100%">
      <el-aside width="30em">
        <el-row align="middle" style="margin-top: 0.8em">
          <el-col :span="18" :offset="2">
            当前文档：
            <el-select
                style="width: 12em"
                value-key="id"
                filterable
                @change="findMenu"
                v-model="documentsInfo.currentDocument"
            >
              <el-option
                  v-for="item in documentsInfo.documents"
                  :label="item.docName"
                  :value="item"
                  :key="item.id"
                  :title="item.docDesc"
              />
            </el-select>
          </el-col>
        </el-row>
        <h3 style="text-align: center">文档目录</h3>
        <el-row align="middle" style="margin-bottom: 6px">
          <el-col :span="3" :offset="2"> 查询：</el-col>
          <el-col :span="10">
            <el-input v-model="filterApiText" clearable size="small"
                      @blur="filterNodeDo" @keydown.enter="filterNodeDo"
                      placeholder="输入uri、名称或说明进行筛选"/>
          </el-col>
          <el-col :span="2">
            <el-button size="small" @click="findMenu" circle title="刷新目录">
              <el-icon>
                <Refresh/>
              </el-icon>
            </el-button>
          </el-col>
          <el-col :span="5">
            <el-button size="small" v-if="writeFlag" @click="addTopMenu">增加目录</el-button>
          </el-col>
        </el-row>

        <el-upload
            class="upload-demo"
            :action="fileUploadUri"
            :before-upload="beforeUpload"
            :on-success="handleSuccess"
            :on-error="handleError"
            multiple
            :limit="1"
            :on-exceed="handleExceed"
            :file-list="fileList">
          <el-button size="small" type="primary">点击上传</el-button>
          <div slot="tip" class="el-upload__tip">只能上传《Talend API Tester》导出的json文件，且不超过5mb</div>
        </el-upload>

        <el-tree
            style="width: 100%"
            :props="treeDefaultProp"
            :data="documentsInfo.currentMenus"
            ref="apiMenuTree"
            :filter-node-method="filterNode"
            :expand-on-click-node="false"
            draggable
            node-key="id"
            @node-drag-end="handleDragApiEnd"
        >
          <template #default="{ node, data }">
            <!-- 图片 -->
            <span class="apiMenuRow">
              <el-icon
                  v-if="data.menuType === 0"
                  style="margin: 2px; padding-top: 4px"
              >
                <Folder/>
              </el-icon>
              <el-icon
                  v-if="data.menuType === 1"
                  style="margin: 2px; padding-top: 4px"
              >
                <Link/>
              </el-icon>
            </span>

            <!-- 目录名称 -->
            <span
                class="apiMenuRow"
                :title="data.desc"
                v-if="data.menuType === 0"
            >
              <span class="apiMenuRow">
                {{ getParentIndex(node) }}{{ data.menuName }}
              </span>
            </span>
            <!-- 接口信息 -->
            <span class="apiMenuRow" v-else>
              <span class="apiMenuRow" v-if="data.apiId">
                <span
                    class="apiMenuRow"
                    :title="getUriDesc(data)"
                    @click="findApiInfo(data)"
                    v-if="data.menuType === 1"
                >
                  {{ getParentIndex(node) }}{{ data.apiName }}
                </span>
              </span>
              <span class="apiMenuRow" v-else>
                {{ data.menuName }}
              </span>
            </span>

            <!-- 操作 -->
            <span class="apiMenuRow" v-if="writeFlag">
              <!-- 增加下级 -->
              <el-button
                  size="small"
                  circle
                  text
                  v-if="data.menuType === 0"
                  @click="addApiMenu(data)"
                  style="margin-left: 6px"
                  title="增加下级"
              >
                <el-icon>
                  <Plus/>
                </el-icon>
              </el-button>
              <el-button
                  size="small"
                  text
                  style="margin: 0 6px"
                  @click="updateMenuBegin(data)"
                  title="修改"
              >
                <el-icon>
                  <Edit/>
                </el-icon>
              </el-button>
              <el-switch
                  size="small"
                  @change="upsertMenu(data, false)"
                  v-model="data.enableFlag"
                  :active-value="1"
                  :inactive-value="0"
                  active-text="启"
                  inactive-text="停">
              </el-switch>

              <el-button size="small" text title="删除目录" type="danger" @click="deleteMenu(node, data)"
                         style="margin: 0 6px">
                <el-icon><Delete/></el-icon>
              </el-button>
            </span>
          </template>
        </el-tree>
      </el-aside>

      <doc-body-all
          :documents-info="documentsInfo"
          @custom-event="handleCustomEvent"
          :write-flag="writeFlag"
          :update-flag="updateFlag"
          :find-api-info-do="findApiInfoDo"
      />

      <el-aside width="20em">
        <br>
        <h4>{{ documentsInfo.currentApiInfo.apiInfo.apiName }}</h4>
        接口说明目录（预留）
        <br>
        <br>
        <br>
      </el-aside>
    </el-container>
  </div>

  <!-- chatGPT生成 -->
  <el-dialog :title="docDialogTitle" v-model="docUpdateFlag" width="40em">
    <div style="margin: 2em">
      <el-form
          :model="documentsInfo.currentDocument"
          :rules="rules"
          ref="docUpdateRef"
          label-width="80px">
        <el-form-item label="文档名称" prop="docName">
          <el-input
              v-model="documentsInfo.currentDocument.docName"
              placeholder="请输入文档名称"
          ></el-input>
        </el-form-item>
        <el-form-item label="文档描述" prop="docDesc">
          <el-input
              v-model="documentsInfo.currentDocument.docDesc"
              type="textarea"
              :autosize="{ minRows: 2, maxRows: 4 }"
              placeholder="请输入文档描述"
          ></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="stateId">
          <el-select
              v-model="documentsInfo.currentDocument.stateId"
              placeholder="请选择状态"
              filterable
          >
            <el-option
                v-for="item in stateOptions"
                :key="item.id"
                :label="item.stateName"
                :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="发布范围" prop="published">
          <el-radio-group v-model="documentsInfo.currentDocument.published">
            <el-radio :label="0">非公开</el-radio>
            <el-radio :label="1">公开</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="docUpdateFlag = false">取 消</el-button>
        <el-button type="primary" @click="submitForm('docUpdateRef')"
        >确 定</el-button
        >
      </span>
    </div>
  </el-dialog>

  <!-- 增加或修改目录 -->
  <el-dialog :title="menuTitle" v-model="menuDialog" width="40em" draggable>
    <div>
      <!-- gpt生成 -->
      <el-form
          :model="menu"
          :rules="menuRules"
          ref="menuRef"
          label-width="100px">
        <el-form-item label="名称" prop="menuName">
          <el-input
              v-model="menu.menuName"
              placeholder="请输入菜单名称"
              minlength="2"
              maxlength="20"/>
        </el-form-item>
        <el-form-item label="描述" prop="apiDesc">
          <el-input v-model="menu.desc" placeholder="请输入接口描述" type="textarea"></el-input>
        </el-form-item>

        <el-form-item label="目录启用" prop="enableFlag">
          <el-radio-group v-model="menu.enableFlag" size="small">
            <el-radio-button :label="0">停用</el-radio-button>
            <el-radio-button :label="1">启用</el-radio-button>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="类型" prop="menuType">
          <el-radio-group v-model="menu.menuType" size="small">
            <el-radio-button :label="0">目录</el-radio-button>
            <el-radio-button :label="1">接口</el-radio-button>
          </el-radio-group>
        </el-form-item>

        <template v-if="menu.menuType === 1">
          <el-form-item label="添加类型" prop="addType">
            <el-radio-group v-model="addMenuType" size="small">
              <el-radio-button :label="0">新增接口</el-radio-button>
              <el-radio-button :label="1">绑定接口</el-radio-button>
            </el-radio-group>
          </el-form-item>

          <template v-if="addMenuType === 0">
            <el-form-item label="接口类型" prop="apiType" size="small">
              <el-radio-group v-model="menu.apiType">
                <el-radio-button :label="'GET'">GET</el-radio-button>
                <el-radio-button :label="'POST'">POST</el-radio-button>
                <el-radio-button :label="'PUT'">PUT</el-radio-button>
                <el-radio-button :label="'DELETE'">DELETE</el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="路由" prop="apiUri">
              <el-input
                  v-model="menu.apiUri"
                  placeholder="请输入接口地址"
              ></el-input>
            </el-form-item>
          </template>

          <template v-if="addMenuType === 1">
            <el-form-item label="选择接口" prop="apiId">
              <el-select v-model="apiInfoAdd" style="width: 90%" filterable remote value-key="id" clearable
                         :remote-method="findApiLike" :loading="loading" @change="changeApiInfo"
                         placeholder="输入接口名称或uri搜索">
                <!-- 这里需要根据实际情况填充接口列表 -->
                <el-option v-for="item in apiArr"
                           :key="item.id" :label="item.apiName +getApiDesc(item)" :value="item">
                </el-option>
              </el-select>
              <el-tooltip class="item" effect="dark" content="同一文档接口不能重复且只能搜索启用接口。"
                          placement="top-end">
                <el-icon>
                  <QuestionFilled/>
                </el-icon>
              </el-tooltip>
            </el-form-item>
          </template>
        </template>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="menuDialog = false">取 消</el-button>
        <el-button type="primary" @click="submitMenuForm()">确 定</el-button>
      </div>
    </div>
  </el-dialog>
</template>

<script>
// @ is an alias to /src
import myaxios from "@/plugins/myaxios";
import axios from "@/plugins/myaxios";
import ApiDocConstants from "@/utils/api-utils/ApiDocConstants";
import {ElMessage} from "element-plus";
import CommonUtils from "@/utils/CommonUtils";
import {Delete, Edit, Folder, Link, Plus, Refresh, QuestionFilled} from "@element-plus/icons-vue";
import DocBodyAll from "@/components/document/DocBodyAll";
import FormRules from "@/utils/FormRules";

export default {
  name: "HomeView",
  components: {
    Delete,
    DocBodyAll,
    Folder,
    Plus,
    Edit,
    Link,
    Refresh,
    QuestionFilled
  },
  methods: {
    handleDragApiEnd(draggingNode, dropNode, dropType, ev) {
      if (draggingNode.data.id === dropNode.data.id) {
        console.log("自己");
        return;
      }
      if (dropType !== "inner") {
        // 调整顺序
        if (dropType === "before") {
          this.setOrder(draggingNode.data.id, dropNode.data.id, 0);
        } else {
          this.setOrder(draggingNode.data.id, dropNode.data.id, 1);
        }
      } else {
        // 调整树结构
        this.setParent(draggingNode, dropNode);
      }
    },
    setParent(draggingNode, dropNode) {
      draggingNode.data.parentId = dropNode.data.id
      let dropChildren = dropNode.data.children
      draggingNode.data.orderNo = dropChildren && dropChildren.length > 1 ? (dropChildren[dropChildren.length - 2].orderNo + 1) : 1
      draggingNode.data.idPath = dropNode.data.idPath + "," + dropNode.data.id
      axios.post("/dist/document/upsertDocMenu", draggingNode.data).then(rep => {
        if (rep.data.code !== 100) {
          ElMessage.error(rep.data.msg)
          return;
        }
        ElMessage.success("移动目录成功。")
      }, err => {
        ElMessage.error('移动失败！')
      })
    },
    setOrder(nodeDataId, dropNodeId, type) {
      let update = "/dist/document/orderChangeMenu"
      axios.post(update, {
            moveId: nodeDataId,
            dropId: dropNodeId,
            type: type
          }
      ).then(rep => {
        if (rep.data.code !== 100) {
          ElMessage.error(rep.data.msg)
          return;
        }

        ElMessage.success("移动目录成功。")
      }, err => {
        ElMessage.error('移动失败！')
      })
    },
    findDocInfo() {
      myaxios.get("/dist/document/getReadDocuments").then(
          rep => {
            if (rep.data.code !== 100) {
              ElMessage.error(rep.data.msg)
              return
            }
            this.documentsInfo = rep.data.data;
            this.writeFlag = this.documentsInfo.createFlag
            this.updateFlag = this.documentsInfo.createFlag
            if (
                this.documentsInfo.createFlag &&
                this.documentsInfo.documents &&
                this.documentsInfo.documents.length === 0
            ) {
              this.docUpdateFlag = true;
              console.log("doc update flag", this.docUpdateFlag);
            } else {
              this.apiId = this.documentsInfo.currentApiInfo.apiInfo.id
            }
          },
          err => {
          }
      );
    },
    submitForm(refStr) {
      this.$refs.docUpdateRef.validate(valid => {
        if (valid) {
          // 使用axios post请求提交  TODO 设置工作空间id
          myaxios
              .post("/dist/document/addDoc", this.documentsInfo.currentDocument)
              .then(
                  res => {
                    // 处理res
                    this.findDocInfo();
                    this.docUpdateFlag = false;
                  },
                  err => {
                    ElMessage.error(err.response.data);
                  }
              );
        }
      });
    },
    addTopMenu() {
      if (!this.documentsInfo || !this.documentsInfo.currentDocument) {
        ElMessage.warning("文档不存在能行新增目录。");
        return;
      }
      this.menu = CommonUtils.cloneObj(ApiDocConstants.docMenu);
      this.menuDialog = true;
      this.menu.docId = this.documentsInfo.currentDocument.id;
      this.menuUpsertType = 0;
      this.menuTitle = "增加一级目录数据";
    },
    submitMenuForm() {
      this.$refs.menuRef.validate(valid => {
        if (valid) {
          // 使用axios post请求提交
          this.upsertMenu(this.menu, true);
        }
      });
    },
    upsertMenu(menuData, addChildren) {
      myaxios.post("/dist/document/upsertDocMenu", menuData).then(
          res => {
            // 处理res
            if (res.data.code !== 100) {
              ElMessage.error(res.data.msg);
              return;
            }

            if (addChildren) {
              const {data} = res.data;
              if (this.menuUpsertType === 0) {
                this.documentsInfo.currentMenus.push(data);
              } else if (this.menuUpsertType === 1) {
                const {children} = this.menuParent;
                if (children) {
                  if (data.menuType === 1) {
                    data.menuName = data.apiName;
                  }
                  children.push(data);
                } else {
                  this.menuParent.children = [data];
                }
              }
            }
            ElMessage.success('操作目录成功。');
            this.menuDialog = false;
          },
          err => {
            ElMessage.error("服务器错误，操作失败。");
          }
      );
    },
    addApiMenu(data) {
      console.log('add menu', data)
      this.menuParent = data;
      this.menu = CommonUtils.cloneObj(ApiDocConstants.docMenu);
      this.menu.docId = data.docId;
      this.menu.parentId = data.id;
      this.menu.idPath = data.idPath + "," + data.id;
      this.menuUpsertType = 1;
      this.menuTitle = data.menuName + " 增加下级";
      this.menuDialog = true;
    },
    updateMenuBegin(data) {
      this.menu = data;
      this.menuUpsertType = 2;
      this.menuTitle = data.menuName + " 修改";
      this.menuDialog = true;
    },
    findApiInfo(data) {
      this.apiId = data.apiId;
      this.findApiInfoDo();
    },
    findApiInfoDo() {
      let uri = "/dist/api/getApiInfo/" + this.apiId + "/" + 1;
      myaxios.get(uri).then(rep => {
        if (rep.data.code !== 100) {
          ElMessage.error(rep.data.msg);
          return;
        }
        this.documentsInfo.currentApiInfo = rep.data.data;
        if (!this.documentsInfo.currentApiInfo.currentParamHis) {
          this.documentsInfo.currentApiInfo.currentParamHis =
              ApiDocConstants.documentsInfo.currentApiInfo.currentParamHis;
        }
      });
    },
    findMenu() {
      let spaceId = this.$store.state.space.id
      let uri = `/dist/document/getDocMenu/${this.documentsInfo.currentDocument.id}/${spaceId}`;
      myaxios.get(uri).then(rep => {
        if (rep.data.code !== 100) {
          ElMessage.error(rep.data.msg);
          return;
        }
        let data = rep.data.data;
        this.documentsInfo.currentApiInfo = data.currentApiInfo;
        this.documentsInfo.currentMenus = data.currentMenus;
        this.documentsInfo.currentDocument = data.currentDocument;
        this.documentsInfo.createFlag = data.createFlag;
        ElMessage.success("查询文档目录成功");
      });
    },
    getUriDesc(menuData) {
      return menuData.apiDesc + "\n" + menuData.apiType + " " + menuData.apiUri;
    },
    handleCustomEvent(payload) {
      this.writeFlag = payload;
    },
    getParentIndex(node) {
      let index = '';
      const parent = this.$refs.apiMenuTree.getNode(node.parent);
      if (parent) {
        index = this.getParentIndex(parent);
        index += parent.childNodes.indexOf(node) + 1 + '.';
      }
      return index;
    },
    deleteMenu(node, data) {
      let childrenStr = ''
      if (data.children && data.children.length > 0) {
        childrenStr = '及其子'
      }
      let tt = data.menuType === 1 ? data.apiName : data.menuName
      console.log(tt)
      let msg = `确定要删除《${tt}》${childrenStr}目录吗？`
      this.$confirm(msg, '确认删除', {
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(() => {
        myaxios.delete(`/dist/document/menu/${data.id}`).then(rep => {
          // 处理res
          if (rep.data.code !== 100) {
            ElMessage.error(rep.data.msg);
            return;
          }
          // 删除对应目录
          node && node.remove();
          ElMessage.success('删除目录成功。')
        }, err => {
          ElMessage.error('移动失败！')
        })
      })
    },
    filterNode(value, data) {
      if (!value || value === '') {
        return true
      }
      return (data.menuName && data.menuName.indexOf(value) > -1) || (data.apiName && data.apiName.indexOf(value) > -1) ||
          (data.desc && data.desc.indexOf(value) > -1) || (data.apiDesc && data.apiDesc.indexOf(value) > -1) ||
          (data.apiUri && data.apiUri.indexOf(value) > -1)
    },
    // 触发目录节点筛选
    filterNodeDo() {
      this.$refs.apiMenuTree.filter(this.filterApiText);
    },
    findApiLike(query) {
      if (query !== '') {
        this.loading = true
        setTimeout(() => {
          let apiLike = {
            apiName: query,
            apiUri: query,
            spaceId: this.$store.state.space.id,
            enableFlag: 1
          }
          // 调用接口进行搜索
          myaxios.post(`/dist/api/findApiLike/${this.documentsInfo.currentDocument.id}`, apiLike).then(response => {
            // 处理接口返回数据
            const data = response.data

            // 将搜索结果赋值给接口列表
            if (data.code !== 100) {
              ElMessage.error(data.msg)
            } else {
              this.apiArr = data.data
            }

            // 取消加载状态
            this.loading = false
          })
        }, 200)
      } else {
        this.apiArr = []
      }
    },
    getApiDesc(apiInfo) {
      return `(${apiInfo.apiType}-${apiInfo.apiUri})`
    },
    changeApiInfo() {
      this.menu.apiId = this.apiInfoAdd.id
      this.menu.apiType = this.apiInfoAdd.apiType
      this.menu.apiUri = this.apiInfoAdd.apiUri
      this.menu.menuName = this.apiInfoAdd.apiName
      this.menu.desc = this.apiInfoAdd.apiDesc
      this.menu.enableFlag = this.apiInfoAdd.enableFlag
    },
    handleSuccess(rep) {
      this.fileList = []
      if (rep.code !== 100) {
        ElMessage.error(rep.msg)
        return
      }
      this.findMenu()
    },
    beforeUpload() {
      let spaceId = this.$store.state.space.id
      this.fileUploadUri = `/dist/file/updateJson/${spaceId}/${this.documentsInfo.currentDocument.id}`
    },
    handleError(rep) {
      this.fileList = []
      ElMessage.error("导入文档失败。")
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    }
  },
  data() {
    return {
      treeDefaultProp: {
        children: "children",
        label: "menuName",
      },
      filterApiText: "",
      documentsInfo: ApiDocConstants.documentsInfo,
      docUpdateFlag: false,
      docDialogTitle: "增加文档",
      rules: {
        docName: [
          {required: true, message: "请输入文档名称", trigger: "blur"},
          {
            min: 1,
            max: 30,
            message: "长度在 1 到 30 个字符",
            trigger: "blur",
          },
        ],
      },
      stateOptions: [
        {id: 1, stateName: "开发中", stateDesc: "开发中"},
        {id: 2, stateName: "测试中", stateDesc: "测试中"},
        {id: 3, stateName: "使用中", stateDesc: "使用中"},
        {id: 4, stateName: "待下线", stateDesc: "待下线"},
      ],
      token: "test",
      menuTitle: "增加目录",
      menuDialog: false,
      menu: ApiDocConstants.docMenu,
      addMenuType: 0,
      menuRules: {
        menuName: FormRules.rules.name,
        apiUri: FormRules.rules.apiUri,
        enableFlag: FormRules.rules.enableFlag,
        menuType: FormRules.rules.menuType,
        apiType: FormRules.rules.apiType,
        apiId: FormRules.rules.apiId
      },
      // 0增加顶层，1增加非顶层，2修改
      menuUpsertType: 0,
      menuParent: {},
      apiId: 1,
      writeFlag: true,
      updateFlag: true,
      loading: false,
      apiArr: [],
      apiInfoAdd: ApiDocConstants.apiInfo,
      fileList: [],
      fileUploadUri: "/dist/file/updateJson"
    };
  },
  watch: {
    filterApiText(val) {
      this.$refs.apiMenuTree.filter(val);
    }
  },
  mounted() {
    this.findDocInfo();
  },
};
</script>

<style>
.home {
  height: 100%;
  width: 100%;
}

.el-aside {
  background-color: rgba(196, 213, 196, 0.2);
  /*background-color: rgba(229, 250, 229, 0.2);*/
  margin-top: 0 !important;
}

.apiMenuRow {
  font-size: 16px;
}

.el-main {
  margin-top: 0;
}

.upload-demo {
  margin-bottom: 4px;
}
</style>
